STM32F4XX 学习日志:定时器中断模拟PWM波实现呼吸灯

您所在的位置:网站首页 stm32 pwm波中断 STM32F4XX 学习日志:定时器中断模拟PWM波实现呼吸灯

STM32F4XX 学习日志:定时器中断模拟PWM波实现呼吸灯

#STM32F4XX 学习日志:定时器中断模拟PWM波实现呼吸灯| 来源: 网络整理| 查看: 265

STM32F4XX 学习日志:定时器中断模拟PWM波实现呼吸灯 前言任务目标解决办法过程定时器配置标准库时钟主频配置出现问题中断服务函数主函数小结以上代码亲测有效。

前言 使用反客科技STM32F407VET6 M1的核心板,板载8M主时钟晶振(HSE),32.768kHz低速外部晶振(LSE)。含有一个用户LED以及一个用户按键。 任务目标

初学使用标准库开发,学长布置了使用定时器产生PWM波来实现呼吸灯的任务。 但是这块板子上的LED灯接在PC13的引脚上。查询了最小原理图以及数据手册后发现,PC13并没有定时器复用功能。 在这里插入图片描述

在这里插入图片描述

解决办法

使用更新中断以及输出比较中断实现模拟pwm波

过程

配置一个定时器两个中断,定时器设置为向上计数。设置TIM1_CC_IRQHandler(void) TIM1_UP_TIM10_IRQHandler(void) 其中更新中断比较常用我就不说了。但是这一个TIM1_CC_IRQHandler中断服务函数在网上见的很少,我在网上多方查找没有结果之后,去翻了数据手册,看到这样的一段介绍。 在这里插入图片描述 以上为比较中断服务函数,当该位置1的时候表示定时器计数值与设定值相等,即

TIM_OCInitStructure.TIM_Pulse = 0;

基数值等于该值的时候,也就是

TIM1->CNT=TIM1->CCR1

这两个寄存器的值相等时,发生中断。 对此就有了两个中断。 假设主频168MHZ设置预分频168-1 计数值100-1 该定定时器上溢中断发生的周期就为 168 000 000 / 168 =1us*100=100us 则将此周期视为pwm频率 而占空比可以通过控制输出比较中断触发的事件来设置。 即设定CCR1的值

TIM1->CCR1

该值与定时器重装载值的商即为占空比。通过在主函数里调整CCR1的值以此来模拟占空比可调的PWM波。

定时器配置 #include "tim.h" void Tim_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 1. 使能时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_TIM8, ENABLE); //TIM_DeInit(TIM1); /* 2. 配置定时器参数 */ TIM_TimeBaseStructure.TIM_Prescaler = 168 - 1; /* 定时器时钟分频系数 */ TIM_TimeBaseStructure.TIM_Period = 1000 - 1; /* 定时器重装载值 */ TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /* 计数器模式 */ TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; /* 重复计数值 */ TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //设置每次进入中断为电平翻转模式 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; //输出开 TIM_OCInitStructure.TIM_Pulse = 0; //设置最初CCR为0,这样一配置完就进去中断服务程序 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //设置最开始的电平为高电平 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //载入寄存器 // TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable); //这里就是参考手册里说的禁用预装载寄存器 /* 3. 配置定时器中断优先级 */ NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn|TIM1_CC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ClearFlag(TIM1, TIM_FLAG_Update); TIM_ClearFlag(TIM1, TIM_FLAG_CC1); /* 4. 使能定时器中断 */ TIM_ITConfig(TIM1, TIM_IT_Update , ENABLE); TIM_ITConfig(TIM1, TIM_FLAG_CC1 , ENABLE); /* 5. 使能定时器 */ TIM_Cmd(TIM1, ENABLE); } 标准库时钟主频配置出现问题

配置结束后测试时出现了一点问题,调试之后发现是时钟频率有问题导致分给定时器的时钟出现问题,TIM1挂载在APB2上,而库函数默认配置HSE作为系统时钟源,设置主频168MHz。但是当我获取PCLK2时钟频率后发现该线上的时钟频率是一个非常奇怪的数字,由此我判断是系统时钟出现问题。 对此我重新设置了高速内部时钟源作为系统时钟源。 下面贴出代码

#include "systemclk.h" #define PLL_M 8 #define PLL_N 168 /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 2 #define PLL_Q 7 /** * @brief Configures HSI as the System clock source **/ void HSI_SetSysClock(void) { __IO uint32_t HSIStartUpStatus = 0; RCC_DeInit(); //set HSI RCC_HSICmd(ENABLE); HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY; if (HSIStartUpStatus == RCC_CR_HSIRDY) { /* Select regulator voltage output Scale 1 mode */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_VOS; // HCLK = SYSCLK / 1 RCC_HCLKConfig(RCC_SYSCLK_Div1); /* HCLK = SYSCLK / 1*/ RCC->CFGR |= RCC_CFGR_HPRE_DIV1; #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx) /* PCLK2 = HCLK / 2*/ RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; /* PCLK1 = HCLK / 4*/ RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; #endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx || STM32F412xG || STM32F446xx || STM32F469_479xx */ #if defined(STM32F401xx) || defined(STM32F413_423xx) /* PCLK2 = HCLK / 1*/ RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; /* PCLK1 = HCLK / 2*/ RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; #endif /* STM32F401xx || STM32F413_423xx */ #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx) /* Configure the main PLL */ RCC->PLLCFGR = PLL_M | (PLL_N 1) -1) } PWR->CR |= PWR_CR_ODSWEN; while((PWR->CSR & PWR_CSR_ODSWRDY) == 0) { } /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; #endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */ #if defined(STM32F40_41xxx) || defined(STM32F412xG) /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; #endif /* STM32F40_41xxx || STM32F412xG */ #if defined(STM32F413_423xx) /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS; #endif /* STM32F413_423xx */ #if defined(STM32F401xx) /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS; #endif /* STM32F401xx */ /* Select the main PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= RCC_CFGR_SW_PLL; /* Wait till the main PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL) { } } }

之后获取时钟频率,HCLK,PCLK2总线频率为168MHz,正常。 继续下面的步骤

中断服务函数 void TIM1_UP_TIM10_IRQHandler(void) { GPIO_SetBits(GPIOC,GPIO_Pin_13); // GPIO_ToggleBits(GPIOC,GPIO_Pin_13); TIM_ClearFlag(TIM1, TIM_FLAG_Update); //清除标志位 } void TIM1_CC_IRQHandler(void) { GPIO_ResetBits(GPIOC,GPIO_Pin_13); // GPIO_ToggleBits(GPIOC,GPIO_Pin_13); TIM_ClearFlag(TIM1, TIM_FLAG_CC1); //清除标志位 } 主函数 #include "main.h" #include "gpio.h" #include "delay.h" #include "systemclk.h" static uint16_t count=0,flag=1; int main(void) { HSI_SetSysClock(); delay_init(); GPIO_init(); Tim_Init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 while(1) { for(count=1;count TIM1->CCR1 = count; STD_Delay_ms(10); } // RCC_ClocksTypeDef Get_RCC_Clocks; } } 小结

本例子只用于学习熟悉了STM32,TIM1_CC_IRQHandler中断,定时器等配置。实际运用时由于不停的触发中断,造成系统处理效率极低。不宜使用。

**

以上代码亲测有效。

**



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3